import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

class TradingStrategy:
    """交易策略类，用于实现各种交易策略"""
    
    def __init__(self):
        """初始化交易策略"""
        self.logger = logging.getLogger('TradingStrategy')
    
    def calculate_ma(self, data, window):
        """计算移动平均线
        
        Args:
            data: 包含收盘价的DataFrame
            window: 移动平均窗口大小
        
        Returns:
            添加了移动平均线的DataFrame
        """
        if '收盘价' in data.columns:
            ma_col = f'MA{window}'
            data[ma_col] = data['收盘价'].rolling(window=window).mean()
        return data
    
    def calculate_technical_indicators(self, data):
        """计算技术指标
        
        Args:
            data: 包含OHLC数据的DataFrame
        
        Returns:
            添加了技术指标的DataFrame
        """
        # 确保数据按日期排序
        if '日期' in data.columns:
            data = data.sort_values('日期')
        
        # 计算移动平均线
        data = self.calculate_ma(data, 5)
        data = self.calculate_ma(data, 10)
        data = self.calculate_ma(data, 20)
        data = self.calculate_ma(data, 60)
        
        # 计算成交量变化
        if '成交量' in data.columns:
            data['成交量变化'] = data['成交量'].pct_change() * 100
            data['成交量MA5'] = data['成交量'].rolling(window=5).mean()
            data['成交量比'] = data['成交量'] / data['成交量MA5']
        
        return data
    
    def stable_strategy_buy_signal(self, data, current_price):
        """稳健型策略买入信号
        
        条件：股价跌5%-10%到20日均线附近（±5%），成交量缩（回调确认）
        
        Args:
            data: 包含技术指标的DataFrame
            current_price: 当前价格
        
        Returns:
            (signal, reason): 信号(True/False)和原因
        """
        if data.empty or 'MA20' not in data.columns or '成交量比' not in data.columns:
            return False, "数据不足或缺少必要指标"
        
        # 获取最新数据
        latest = data.iloc[-1]
        previous = data.iloc[-2] if len(data) > 1 else None
        
        # 获取20日均线
        ma20 = latest['MA20']
        if pd.isna(ma20):
            return False, "20日均线数据不足"
        
        # 计算当前价格与前一交易日收盘价的跌幅
        if previous is not None and '收盘价' in previous:
            prev_close = previous['收盘价']
            price_drop = (current_price - prev_close) / prev_close * 100
        else:
            # 如果没有前一交易日数据，使用当前价格与最新收盘价比较
            prev_close = latest['收盘价']
            price_drop = (current_price - prev_close) / prev_close * 100
        
        # 计算当前价格与20日均线的偏离度
        ma20_deviation = (current_price - ma20) / ma20 * 100
        
        # 检查成交量是否缩小
        volume_shrinking = latest['成交量比'] < 1.0 if '成交量比' in latest else False
        
        # 买入条件：
        # 1. 股价跌5%-10%
        # 2. 当前价格在20日均线附近（±5%）
        # 3. 成交量缩小
        if -10 <= price_drop <= -5 and abs(ma20_deviation) <= 5 and volume_shrinking:
            reason = f"股价跌幅{price_drop:.2f}%，接近20日均线(偏离{ma20_deviation:.2f}%)，成交量缩小"
            return True, reason
        
        return False, "不符合稳健型买入条件"
    
    def high_return_strategy_buy_signal(self, data, current_price):
        """高收益型策略买入信号
        
        条件1（低吸）：开盘跌2%-6%，量缩（恐慌抛售）或放量（资金抢筹）
        条件2（突破）：突破20日/52周高点后回踩5%，量增2倍
        
        Args:
            data: 包含技术指标的DataFrame
            current_price: 当前价格
        
        Returns:
            (signal, reason, type): 信号(True/False)、原因和类型（低吸/突破）
        """
        if data.empty or 'MA20' not in data.columns or '成交量比' not in data.columns:
            return False, "数据不足或缺少必要指标", None
        
        # 获取最新数据
        latest = data.iloc[-1]
        previous = data.iloc[-2] if len(data) > 1 else None
        
        # 检查低吸条件
        if previous is not None and '收盘价' in previous:
            prev_close = previous['收盘价']
            price_drop = (current_price - prev_close) / prev_close * 100
            
            # 低吸条件：开盘跌2%-6%，量缩或放量
            if -6 <= price_drop <= -2:
                volume_ratio = latest['成交量比']
                
                if volume_ratio < 0.8:  # 量缩（恐慌抛售）
                    reason = f"股价跌幅{price_drop:.2f}%，成交量缩小(比值{volume_ratio:.2f})，可能是恐慌抛售"
                    return True, reason, "低吸"
                elif volume_ratio > 1.5:  # 放量（资金抢筹）
                    reason = f"股价跌幅{price_drop:.2f}%，成交量放大(比值{volume_ratio:.2f})，可能是资金抢筹"
                    return True, reason, "低吸"
        
        # 检查突破回踩条件
        # 1. 找到20日内最高价
        if len(data) >= 20:
            recent_data = data.iloc[-20:]
            max_high = recent_data['最高价'].max()
            
            # 2. 检查是否之前突破后现在回踩
            if previous is not None and previous['最高价'] >= max_high:
                # 计算从最高点回踩的幅度
                pullback = (current_price - max_high) / max_high * 100
                
                # 检查成交量是否放大
                volume_ratio = latest['成交量比']
                
                if -7 <= pullback <= -3 and volume_ratio >= 2.0:
                    reason = f"突破20日高点后回踩{pullback:.2f}%，成交量是均值的{volume_ratio:.2f}倍"
                    return True, reason, "突破"
        
        return False, "不符合高收益型买入条件", None
    
    def calculate_stop_loss(self, strategy_type, buy_price, ma_data):
        """计算止损价格
        
        稳健型：跌8%或跌破60日均线（取较严者）
        高收益型：跌8%或跌破5日均线（短线用）
        
        Args:
            strategy_type: 策略类型（"稳健型"或"高收益型"）
            buy_price: 买入价格
            ma_data: 包含均线数据的DataFrame
        
        Returns:
            止损价格
        """
        # 计算基于百分比的止损价格
        percent_stop_loss = buy_price * 0.92  # 跌8%
        
        if strategy_type == "稳健型":
            # 获取60日均线
            if not ma_data.empty and 'MA60' in ma_data.columns:
                ma60 = ma_data.iloc[-1]['MA60']
                if not pd.isna(ma60):
                    # 取较低者作为止损价格
                    return min(percent_stop_loss, ma60)
        
        elif strategy_type == "高收益型":
            # 获取5日均线
            if not ma_data.empty and 'MA5' in ma_data.columns:
                ma5 = ma_data.iloc[-1]['MA5']
                if not pd.isna(ma5):
                    # 取较低者作为止损价格
                    return min(percent_stop_loss, ma5)
        
        # 默认返回百分比止损价格
        return percent_stop_loss
    
    def calculate_take_profit(self, strategy_type, buy_price, intrinsic_value=None, signal_type=None):
        """计算止盈价格
        
        稳健型：涨15%-20%或接近内在价值
        高收益型：涨10%-20%（低吸10%，突破20%）
        
        Args:
            strategy_type: 策略类型（"稳健型"或"高收益型"）
            buy_price: 买入价格
            intrinsic_value: 内在价值（可选）
            signal_type: 信号类型（"低吸"或"突破"，仅高收益型适用）
        
        Returns:
            止盈价格
        """
        if strategy_type == "稳健型":
            # 计算基于百分比的止盈价格（15%）
            percent_take_profit = buy_price * 1.15
            
            # 如果有内在价值，取较低者
            if intrinsic_value and intrinsic_value > buy_price:
                return min(percent_take_profit, intrinsic_value)
            
            return percent_take_profit
        
        elif strategy_type == "高收益型":
            if signal_type == "低吸":
                # 低吸策略止盈10%
                return buy_price * 1.1
            elif signal_type == "突破":
                # 突破策略止盈20%
                return buy_price * 1.2
            else:
                # 默认15%
                return buy_price * 1.15
        
        # 默认返回15%止盈价格
        return buy_price * 1.15
    
    def calculate_intrinsic_value(self, pb, net_assets_per_share):
        """计算内在价值
        
        公式：PB × 净资产
        
        Args:
            pb: 合理市净率
            net_assets_per_share: 每股净资产
        
        Returns:
            内在价值
        """
        if pb and net_assets_per_share:
            return pb * net_assets_per_share
        return None
